﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace WebPALTT.Lib
{

    /*
     * Class: ActionItem_Sleep
     *  
     * This class represents a sleep action and inherits from @link[ActionItem.cs.htm, ActionItem].
     */
    [Serializable()]
    public class ActionItem_Sleep : ActionItem
    {
        public override ActionType ActionType { get { return ActionType.Sleep; } }

        int mDuration;
        bool mRandom;
        int mMax;
        int mMin;

        /*
         * Name: Properties
         * 
         * /int/ Duration:
         * 
         * Gets or set the sleep duration in milliseconds.
         * 
         * /bool/ IsRandom:
         * 
         * Gets or set boolean indicating if a random sleep time should be used.
         * If this property is true, the Min and Mix values must be set.
         * 
         * /int/ Min:
         * 
         * Gets or set the minimum sleep duration in milliseconds. (only used if IsRandom is true).
         * 
         * /int/ Max:
         * 
         * Gets or set the maximum sleep duration in milliseconds. (only used if IsRandom is true).
         * 
         * Method: GetSleepDuration
         * 
         * Return the sleep duration of the action.
         * 
         * ++*{{NB:}}* If IsRandom is true, the value returned will not be the actual sleep duration as that is calculated only when the action is run.++
         */

        [DescriptionAttribute("Sleep duration in milliseconds.")]
        public int Duration { get { return mDuration; } set { mDuration = value; } }
        [DescriptionAttribute("Selects a random sleep duration between the minimum and maximum duration.")]
        public bool IsRandom { get { return mRandom; } set { mRandom = value; } }
        [DescriptionAttribute("Minimum sleep duration in milliseconds. \r\n(only used if IsRandom is true)")]
        public int Min { get { return mMin; } set { mMin = value; } }
        [DescriptionAttribute("Maximum sleep duration in milliseconds. \r\n(only used if IsRandom is true)")]
        public int Max { get { return mMax; } set { mMax = value; } }

        /// <summary>
        /// Creates a new sleep action of 0 ms.
        /// </summary>
        /// <param name="name"></param>
        public ActionItem_Sleep(String name) : this(name, 0) { }

        /// <summary>
        /// Creates a new sleep action.
        /// </summary>
        /// <param name="name">name of the action</param>
        /// <param name="duration">duration in milliseconds</param>
        public ActionItem_Sleep(String name, int duration)
            : base(name)
        {
            if (duration < 0)
                throw new Exception("Parameter is incorrect: Sleep value cannot be less than zero.");
            mDuration = duration;
            mRandom = false;
            mMin = 0;
            mMax = 0;
        }

        /// <summary>
        /// Creates a new sleep action with a random sleep time.
        /// </summary>
        /// <param name="name">name of the action</param>
        /// <param name="min">minimum sleep time in milliseconds</param>
        /// <param name="max">maximum sleep time in milliseconds</param>
        public ActionItem_Sleep(String name, int min, int max)
            : base(name)
        {
            if (min < 0)
                throw new Exception("Parameter is incorrect: Sleep value cannot be less than zero.");
            if (max < min)
                throw new Exception("Parameter is incorrect: Maximum value must be greater than minimum.");
            mDuration = 0;
            mRandom = true;
            mMin = min;
            mMax = max;
        }

        public ActionItem_Sleep(SerializationInfo info, StreamingContext ctxt)
            : base(info, ctxt)
        {
            mDuration = (int)info.GetValue("Duration", typeof(int));
            mRandom = (bool)info.GetValue("Random", typeof(bool));
            mMin = (int)info.GetValue("Min", typeof(int));
            mMax = (int)info.GetValue("Max", typeof(int));
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            base.GetObjectData(info, ctxt);
            info.AddValue("Duration", mDuration);
            info.AddValue("Random", mRandom);
            info.AddValue("Min", mMin);
            info.AddValue("Max", mMax);
        }

        public int GetSleepDuration()
        {
            if (this.IsRandom)
                return (new Random().Next(mMin, mMax));
            return mDuration;
        }

        public override string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");

            if (IsRandom)
            {
                if (Max < Min)
                    errors.Add("Error: action[" + Name + "(" + ActionType + ")] - Maximum sleep value must be greater than or equal to minimum.");
                if (Max < 0 || Min < 0)
                    errors.Add("Error: action[" + Name + "(" + ActionType + ")] - Maximum and minimum sleep values must be greater than or equal to zero.");
            }
            else
                if (Duration < 0)
                    errors.Add("Error: action[" + Name + "(" + ActionType + ")]. - Sleep duration must be greater than or equal to zero.");

            return errors.ToArray();
        }

        public override ActionItem GetChild(Guid key) { return null; }
    }
}
